"""
历史分析选品业务模块
"""
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))

import time
import random
import traceback
import logging
from typing import List, Dict, Any
from PyQt6.QtCore import QObject, QThread, pyqtSignal
from com.scan_account_pool import ScanAccountPool
from reqapi.get_csgo_page_list2 import GetCsgoPagedListV2Api
from biz.price_analysis import PriceAnalyzer
from reqapi.get_template_info import GetTemplateInfoApi
import json
from datetime import datetime
import sqlite3
from com.db.task_manager import TaskManager
from com.constants.wear_ranges import WearCategory, WEAR_CATEGORY_RANGES, WEAR_CATEGORY_NAMES, get_wear_ranges

# 配置日志
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

class HistoryAnalysisAutoSelectCommodity(QObject):
    """历史分析选品业务类"""
    
    log_signal = pyqtSignal(str)
    progress_signal = pyqtSignal(int, int)
    result_signal = pyqtSignal(list)
    
    def __init__(self):
        super().__init__()
        self.account_pool = ScanAccountPool()
        self.csgo_api = None
        self.price_analyzer = None
        self.selected_commodities = []
        self.current_processed = 0
        self.total_items = 0
        self.should_stop = False  # 添加停止标志
        self.task_manager = TaskManager()  # 添加任务管理器

    def log(self, message: str):
        """发送日志消息"""
        logger.info(message)
        try:
            self.log_signal.emit(message)
        except:
            print(message)
            
    def stop(self):
        """停止选品"""
        self.should_stop = True
        self.log("正在停止选品...")

    def _get_and_init_account(self):
        """获取账号并初始化API"""
        try:
            # 获取可用账号
            accounts = self.account_pool.get_accounts_with_intervals(1)
            if not accounts:
                self.log("没有可用账号")
                return None
                
            # 获取第一个账号的信息
            account_info = accounts[0]
            account = account_info['account']
            interval = account_info['interval']
            next_available_time = account_info['next_available_time']
            
            logger.info(f"获取到账号 [{account.get('nickname', account.get('name', account.get('id', '未知')))}]，"
                       f"等待时间 {interval} 秒，"
                       f"下次可用时间 {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(next_available_time))}")
            
            return account_info
            
        except Exception as e:
            self.log(f"获取账号时发生错误: {str(e)}")
            return None

    def _fetch_multi_page_items(self, account_info, min_price, max_price, page_count=3) -> list:
        """获取多页商品数据"""
        logger.info("开始获取商品列表...")
        all_items = []
        seen_items = set()  # 用于去重
        
        try:
            # 获取账号信息
            account = account_info['account']
            interval = account_info['interval']
            next_available_time = account_info['next_available_time']
            
            # 等待到账号可用时间
            wait_time = max(0, next_available_time - time.time())
            if wait_time > 0:
                logger.info(f"等待 {wait_time:.2f} 秒后开始获取商品列表...")
                time.sleep(wait_time)
            
            # 创建API实例
            logger.info(f"使用账号 [{account.get('nickname', account.get('name', account.get('id', '未知')))}] 初始化API")
            self.csgo_api = GetCsgoPagedListV2Api(
                device_token=account.get('device_id', ''),
                device_id=account.get('device_id', ''),
                auth_token=account.get('uu_token', ''),
                uk=account.get('uk', '')
            )
            
            # 获取每一页的数据
            for page in range(1, page_count + 1):
                logger.info(f"正在获取第 {page} 页商品数据...")
                
                # 获取商品列表
                response = self.csgo_api.execute(
                    filter_map={
                        "Type": [
                            "CSGO_Type_Pistol_Unlimited",
                            "CSGO_Type_Rifle_Unlimited",
                            "CSGO_Type_SMG_Unlimited",
                            "CSGO_Type_Shotgun_Unlimited",
                            "CSGO_Type_Machinegun_Unlimited"
                        ]
                    },
                    game_id=730,
                    list_sort_type=0,
                    list_type=10,
                    min_price=str(min_price),
                    max_price=str(max_price),
                    page_index=page,
                    page_size=100,
                    property_filter_tags=[],
                    sort_type=0,
                    sticker_abrade=0,
                    stickers_is_sort=False,
                    session_id=account.get('device_id', '')
                )
                
                if not response or response.get('Code') != 0:
                    logger.info(f"获取第 {page} 页商品列表失败: {response.get('Message', '未知错误')}")
                    continue
                    
                # 获取商品列表数据
                items = response.get('Data', {}).get('categoryList', [])
                if not items:
                    logger.info(f"第 {page} 页未找到符合条件的商品")
                    continue
                
                logger.info(f"第 {page} 页获取到 {len(items)} 个商品")
                
                # 将商品添加到字典中，使用商品ID作为键以实现去重
                for item in items:
                    item_id = item.get('Id')
                    if item_id:
                        all_items.append(item)
                        
                
                # 对获取到的三页商品做下去重
                all_items = list({item.get('Id'): item for item in all_items}.values())
            
            logger.info(f"商品列表获取完成，共 {len(all_items)} 个商品")
            return all_items
            
        except Exception as e:
            logger.error(f"获取商品列表时发生错误: {str(e)}")
            return []

    def select_commodities(self, min_price: float, max_price: float, min_sales: int) -> List[Dict[str, Any]]:
        """
        历史分析选品
        
        Args:
            min_price: 最低价格
            max_price: 最高价格
            min_sales: 最小在售数量
            
        Returns:
            list: 选中的商品列表
        """
        try:
            self.should_stop = False  # 重置停止标志
            self.selected_commodities = []  # 清空选中列表
            self.current_processed = 0  # 重置处理计数
            
            logger.info("开始历史分析选品...")
            logger.info(f"筛选条件: 价格范围 {min_price}-{max_price}，最小在售数量 {min_sales}")
            
            # 初始化价格分析器
            self.price_analyzer = PriceAnalyzer()
            
            # 获取所有已存在的任务商品ID
            existing_goods_ids = set()
            try:
                all_tasks = self.task_manager.get_all_tasks()
                existing_goods_ids = {task['goods_id'] for task in all_tasks}
                self.log(f"已存在 {len(existing_goods_ids)} 个任务")
            except Exception as e:
                self.log(f"获取已存在任务失败: {str(e)}")
            
            # 获取账号
            logger.info("正在获取可用账号...")
            account_info = self._get_and_init_account()
            if not account_info:
                logger.error("没有可用账号")
                return []
                
            # 获取商品列表
            logger.info("正在获取商品列表...")
            items = self._fetch_multi_page_items(account_info, min_price, max_price)
            if not items:
                logger.info("未获取到商品数据")
                return []
                
            # 过滤掉已存在任务的商品
            filtered_items = [
                item for item in items 
                if item.get('Id') not in existing_goods_ids
            ]
            self.log(f"过滤掉 {len(items) - len(filtered_items)} 个已存在任务的商品")
            
            # 如果过滤后没有商品，直接返回空列表
            if not filtered_items:
                self.log("没有新的商品需要分析")
                return []
                
            # 设置总商品数
            self.total_items = len(filtered_items)
            self.log(f"共获取到 {self.total_items} 个商品待分析")
            
            # 清空已选商品列表
            self.selected_commodities = []
            
            # 获取与商品数量相同的账号列表
            logger.info(f"正在获取 {len(filtered_items)} 个账号...")
            accounts = self.account_pool.get_accounts_with_intervals(len(filtered_items))
            if not accounts:
                logger.error("获取账号列表失败")
                return []
                
            # 创建线程池
            logger.info("开始创建分析线程...")
            threads = []
            
            # 为每个商品分配一个账号
            for item, account_info in zip(filtered_items, accounts):
                # commodity_name = item.get('CommodityName', '')  # 改用commodityName
                # account = account_info['account']
                # interval = account_info['interval']
                # next_available_time = account_info['next_available_time']
                
                # logger.info(f"商品 [{commodity_name}] 分配账号 [{account.get('nickname', account.get('name', account.get('id', '未知')))}]，"
                #           f"等待时间 {interval} 秒，下次可用时间 {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(next_available_time))}")
                
                # 创建分析线程
                thread = HistoryAnalysisThread(
                    commodity=item,
                    min_sales=min_sales,
                    account_info=account_info,  # 传递完整的账号信息，包含间隔和下次可用时间
                    callback=self.process_analysis_result
                )
                threads.append(thread)
                
            # 启动所有线程
            logger.info(f"开始启动 {len(threads)} 个分析线程...")
            for thread in threads:
                if self.should_stop:  # 检查是否应该停止
                    self.log("选品已停止")
                    break
                thread.start()
                thread.wait()  # 等待当前线程完成后再处理下一个
            
            logger.info(f"分析完成，共找到 {len(self.selected_commodities)} 个符合条件的商品")
            return self.selected_commodities
            
        except Exception as e:
            logger.error(f"选品过程中发生错误: {str(e)}")
            return []
            
    def process_analysis_result(self, analysis_result, commodity_name, template_id, commodity_data, message=None):
        """处理分析结果
        
        Args:
            analysis_result: 分析结果，包含投资评分和建议
            commodity_name: 商品名称
            template_id: 商品模板ID
            commodity_data: 商品数据
            message: 错误消息，如果有的话
        """
        try:
            if message:
                logger.info(message)
                self.log(message)
                return
                
            if not analysis_result:
                self.log(f"商品 {commodity_name} 不符合投资条件")
                return
            
            recommendations = analysis_result.get('recommendations', [])
            if not recommendations:
                self.log(f"商品 {commodity_name} 没有推荐的饰品")
                return
            self.log(f"商品 {commodity_name} 符合投资条件，有 {len(recommendations)} 个推荐饰品")
            
            # 从扫货账号池获取一个账号
            account_pool = ScanAccountPool()
            accounts = account_pool.get_accounts_with_intervals(1)
            if not accounts:
                self.log(f"获取扫货账号失败")
                return
                
            scan_account = accounts[0]['account']
            
            # 遍历推荐的饰品
            for recommendation in recommendations:
                try:
                    
                    # 从推荐数据中获取template_id
                    item_template_id = recommendation.get('template_id')
                    if not item_template_id:
                        print(f"警告：推荐数据缺少template_id字段")
                        continue
                        
                    # 检查是否已经在selected_commodities中
                    if any(str(item_template_id) == str(item.get('template_id')) for item in self.selected_commodities):
                        print(f"跳过已选中的商品 template_id={item_template_id}")
                        continue
                    
                    self.log(f"处理推荐饰品 template_id: {item_template_id}")
                    
                    # 获取商品详细信息
                    template_api = GetTemplateInfoApi(
                        device_id=scan_account['device_id'],
                        device_token=scan_account['device_id'],
                        auth_token=scan_account['uu_token'],
                        uk=scan_account['uk']
                    )
                    
                    template_info = template_api.execute(item_template_id)
                    if not template_info or not template_info.TemplateInfo:
                        self.log(f"获取饰品 {item_template_id} 详细信息失败")
                        continue
                        
                    # 获取外观对应的磨损范围
                    exterior_name = template_info.TemplateInfo.Exterior
                    wear_range = None
                    if exterior_name == "崭新出厂":
                        wear_ranges = get_wear_ranges(WearCategory.FACTORY_NEW)
                        wear_range = wear_ranges[0] if wear_ranges else WEAR_CATEGORY_RANGES[WearCategory.FACTORY_NEW]
                    elif exterior_name == "略有磨损":
                        wear_ranges = get_wear_ranges(WearCategory.MINIMAL_WEAR)
                        wear_range = wear_ranges[0] if wear_ranges else WEAR_CATEGORY_RANGES[WearCategory.MINIMAL_WEAR]
                    elif exterior_name == "久经沙场":
                        wear_ranges = get_wear_ranges(WearCategory.FIELD_TESTED)
                        wear_range = wear_ranges[0] if wear_ranges else WEAR_CATEGORY_RANGES[WearCategory.FIELD_TESTED]
                    elif exterior_name == "破损不堪":
                        wear_ranges = get_wear_ranges(WearCategory.WELL_WORN)
                        wear_range = wear_ranges[0] if wear_ranges else WEAR_CATEGORY_RANGES[WearCategory.WELL_WORN]
                    elif exterior_name == "战痕累累":
                        wear_ranges = get_wear_ranges(WearCategory.BATTLE_SCARRED)
                        wear_range = wear_ranges[0] if wear_ranges else WEAR_CATEGORY_RANGES[WearCategory.BATTLE_SCARRED]
                    
                    # 准备选中商品数据
                    selected_commodity = {
                       "template_id": str(item_template_id),  # 饰品模板ID
                        "name": template_info.TemplateInfo.CommodityName,  # 饰品名称
                        "hash_name": template_info.TemplateInfo.CommodityHashName,  # 饰品哈希名称
                        "wear": f"{wear_range.min_val:.3f}-{wear_range.max_val:.3f}" if wear_range else "0-1",  # 磨损范围
                        "price": f"{recommendation.get('current_price', 0):.2f}",  # 当前市场价格
                        "count": str(template_info.TemplateInfo.OnSaleCount),  # 当前在售数量
                        "steam_price": template_info.TemplateInfo.SteamPrice or "0",  # Steam市场价格
                        "min_price": template_info.TemplateInfo.MinPrice or "0",  # 最低售价
                        "rarity": template_info.TemplateInfo.Rarity,  # 稀有度
                        "quality": template_info.TemplateInfo.Quality,  # 品质
                        "exterior": template_info.TemplateInfo.Exterior,  # 外观
                        "score": f"{recommendation.get('score', 0):.2f}",  # 投资评分
                        "liquidity_score": f"{recommendation.get('liquidity_score', 0):.2f}",  # 流动性评分
                        "price_advantage_score": f"{recommendation.get('price_advantage_score', 0):.2f}",  # 价格优势评分
                        "stability_score": f"{recommendation.get('stability_score', 0):.2f}",  # 稳定性评分
                        "supply_score": f"{recommendation.get('supply_score', 0):.2f}",  # 供需评分
                        "daily_volume": f"{recommendation.get('daily_volume', 0):.2f}",  # 日均成交量
                        "steam_premium": f"{recommendation.get('steam_premium', 0):.2f}%",  # Steam市场溢价率 
                    }

                    # 获取价格分析结果
                    price_analysis = recommendation.get('price_analysis', {})
                    if price_analysis:
                        selected_commodity.update({
                            "suggested_snipe_price": f"{price_analysis.get('suggested_snipe_price', 0):.2f}",  # 建议捡漏价格
                            "theoretical_max_buy_price": f"{price_analysis.get('theoretical_max_buy_price', 0):.2f}",  # 理论最高买入价格
                            "target_sell_price": f"{price_analysis.get('target_sell_price', 0):.2f}",  # 目标售价
                            "historical_success_rate": price_analysis.get('historical_success_rate', {}),  # 历史成功率
                            "price_range_compactness": f"{price_analysis.get('price_range_compactness', 0):.1f}%",  # 价格区间紧凑度
                            "volatility": f"{price_analysis.get('volatility', 0):.1f}%",  # 波动率
                            "trend_analysis": price_analysis.get('trend_analysis', {}),  # 趋势分析
                            'historical_price_range':price_analysis.get('historical_price_range', {}), # 历史价格
                            'cluster_analysis':price_analysis.get('cluster_analysis', {}), # 聚类分析
                        })
                    
                    # print(selected_commodity)

                    # 添加到选中列表
                    self.selected_commodities.append(selected_commodity)
                    # 发送选品结果
                    self.result_signal.emit([selected_commodity])
                    self.log(f"推荐饰品 {selected_commodity['name']} 已添加到选中列表")
                    
                except Exception as e:
                    self.log(f"处理推荐饰品时发生错误: {str(e)}")
                    traceback.print_exc()
                    continue
            
        except Exception as e:
            self.log(f"处理商品 {commodity_name} 分析结果时发生错误: {str(e)}")
            traceback.print_exc()
        finally:
            # 更新进度
            self.current_processed += 1
            self.progress_signal.emit(self.current_processed, self.total_items)
            logger.info(f"已完成 {self.current_processed}/{self.total_items} 个商品的分析")


class HistoryAnalysisThread(QThread):
    """历史分析线程"""
    
    def __init__(self, commodity: dict, min_sales: int, account_info: dict, callback):
        """
        初始化
        
        Args:
            commodity: 商品信息字典，包含Id、CommodityName等字段
            min_sales: 最小在售数量
            account_info: 账号信息，包含账号、间隔和下次可用时间
            callback: 回调函数
        """
        super().__init__()
        self.commodity = commodity
        self.min_sales = min_sales
        self.account_info = account_info
        self.callback = callback
        self.price_analyzer = PriceAnalyzer()
        logger.info(f"商品信息: Id={self.commodity.get('Id')}, 名称={self.commodity.get('CommodityName')}")
        
    def run(self):
        """执行分析"""
        try:
            # 获取账号信息
            account = self.account_info['account']
            next_available_time = self.account_info['next_available_time']
            
            # 从commodity中提取商品名称和模板ID
            commodity_name = self.commodity.get('CommodityName', '')
            template_id = self.commodity.get('Id')
            
            # 等待到账号可用时间
            wait_time = max(0, next_available_time - time.time())
            if wait_time > 0:
                logger.info(f"等待 {wait_time:.2f} 秒后开始分析商品 {commodity_name}...")
                time.sleep(wait_time)
            
            # 调用价格分析器的投资机会分析方法
            logger.info(f"开始分析商品 {commodity_name} 的投资机会...")
            analysis_result = self.price_analyzer.analyze_investment_opportunity(
                template_id=template_id,
                commodity_name=commodity_name,
                min_supply=self.min_sales,
                device_info=account  # 传递账号信息
            )
            
            # 处理分析结果
            if analysis_result:
                logger.info(f"商品 {commodity_name} 分析完成")
                self.callback(analysis_result, commodity_name, template_id, self.commodity)
            else:
                logger.info(f"商品 {commodity_name} 不符合投资条件")
                self.callback(None, commodity_name, template_id, self.commodity,
                            f"商品 {commodity_name} 不符合投资条件")
                
        except Exception as e:
            logger.error(f"分析商品 {commodity_name} 时发生错误: {str(e)}")
            self.callback(None, commodity_name, template_id, self.commodity,
                        f"处理商品 {commodity_name} 时发生错误: {str(e)}")
            traceback.print_exc()


def main():
    """测试入口"""
    try:
        # 设置日志级别
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        
        # 创建分析实例
        analyzer = HistoryAnalysisAutoSelectCommodity()
        
        # 连接信号
        analyzer.log_signal.connect(lambda msg: print(f"[LOG] {msg}"))
        analyzer.progress_signal.connect(lambda cur, total: print(f"[进度] {cur}/{total}"))
        analyzer.result_signal.connect(lambda results: print(f"\n[结果] 找到 {len(results)} 个商品:"))
        analyzer.result_signal.connect(lambda results: [print(
            f"\n商品名称: {item.get('name', '未知')}\n"  
            f"模板ID: {item.get('template_id', '未知')}\n"  
            f"分析结果: {item.get('analysis_result', {})}"
        ) for item in results])
        
        # 设置筛选参数
        params = {
            'min_price': 5,    # 最低价格
            'max_price': 100,  # 最高价格
            'min_sales': 300   # 最小在售数量
        }
        
        print("\n开始执行历史分析选品...")
        print(f"筛选参数: {params}")
        
        # 执行选品
        results = analyzer.select_commodities(**params)
        
        print("\n选品完成!")
        if results:
            print(f"\n共找到 {len(results)} 个符合条件的商品:")
            for item in results:
                print(f"\n商品名称: {item.get('name', '未知')}")  
                print(f"模板ID: {item.get('template_id', '未知')}")  
                print(f"分析结果: {item.get('analysis_result', {})}")
        else:
            print("\n未找到符合条件的商品")
            
    except Exception as e:
        print(f"\n执行过程中发生错误: {str(e)}")
        traceback.print_exc()
        
if __name__ == "__main__":
    main()
